package cn.sxw.ld.task;

import cn.sxw.ld.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;

@Component
public class DatabaseBackupScheduler {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseBackupScheduler.class);

    @Value("${spring.datasource.druid.url}")
    private String dbUrl;

    @Value("${spring.datasource.druid.username}")
    private String dbUsername;

    @Value("${spring.datasource.druid.password}")
    private String dbPassword;

    // 邮件发送相关
    @Value("${spring.mail.username}")
    private String senderEmail;
    @Value("${ling-dan-cat.sqlPath}")
    private String sqlPath;
    @Value("${ling-dan-cat.logPath}")
    private String logPath;
    @Value("${ling-dan.mail.addressee}")
    private String mailAddressee;

    private final JavaMailSender mailSender;

    public DatabaseBackupScheduler(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    // 定时任务，每个月1号中午2点执行一次
//    @Scheduled(cron = "0 */1 * * * ?")
//    @Scheduled(cron = "0 0 14 1 * ?")
    public void backupDatabase() {
        try {
            // 生成备份文件名
            String backupFileName = "database_backup_" + DateUtils.formatDate(System.currentTimeMillis()) + ".sql";
            // sql 保存目录
            String backupsPath = sqlPath + "\\" + backupFileName;
            // log 保存目录
            String log = logPath + "\\application.log";
            String[] backupsAndLog = {backupsPath, log};
            // 执行备份命令
            executeBackupCommand(backupsPath);
            // 发送备份文件到指定邮箱
            sendBackupFileByEmail(backupsAndLog);
            logger.info("备份已发送");
        } catch (Exception e) {
            logger.error("备份失败", e);
        }
    }

    /**
     * 进行数据库 sql 备份
     *
     * @param backupsPath
     * @throws IOException
     * @throws InterruptedException
     */
    private void executeBackupCommand(String backupsPath) throws IOException, InterruptedException {
        // 解析数据库名称
        URI uri = URI.create(dbUrl.replaceFirst("jdbc:", ""));
        String dbName = uri.getPath().split("/")[1];
        // 构建备份命令
        String command = "mysqldump -u " + dbUsername + " -p" + dbPassword + " " + dbName + " > " + backupsPath;
        // 执行命令
        // Windows 系统使用 cmd 执行命令
        Process process = Runtime.getRuntime().exec(new String[]{"cmd", "/c", command});
        int exitCode = process.waitFor();
        if (exitCode != 0) {
            throw new IOException("备份文件不存在" + exitCode);
        }
    }

    /**
     * 将生成的数据库sql与认真文件发送邮件
     *
     * @param backupsAndLog
     * @throws MessagingException
     */
    private void sendBackupFileByEmail(String[] backupsAndLog) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        // 设置发件人、收件人、主题和内容
        helper.setFrom(senderEmail);
        helper.setTo(mailAddressee);
        helper.setSubject("方老板猫店相关");
        helper.setText("数据库定期备份，日志文件");
        for (String backupAndLog : backupsAndLog) {
            File file = new File(backupAndLog);
            if (file.exists()) {
                // 添加附件
                helper.addAttachment(backupAndLog, file);
            }
        }
        // 发送邮件
        mailSender.send(message);
    }
}
